package com.example.basecommon.http;

import android.app.Activity;
import android.net.ParseException;
import android.support.v4.app.FragmentActivity;
import android.util.Log;

import com.example.basecommon.utils.TipsErrorDialog;
import com.google.gson.JsonParseException;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONException;

import java.io.EOFException;
import java.net.ConnectException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
/**
 * @author dlj
 * 请求异常处理类
 */
public class RequestErrorHelper {
    //对应HTTP的状态码
    private static final int REQUEST_ERROR = 400;
    private static final int UNAUTHORIZED = 401;
    private static final int FORBIDDEN = 403;
    private static final int NOT_FOUND = 404;
    private static final int REQUEST_TIMEOUT = 408;
    private static final int INTERNAL_SERVER_ERROR = 500;
    private static final int BAD_GATEWAY = 502;
    private static final int SERVICE_UNAVAILABLE = 503;
    private static final int GATEWAY_TIMEOUT = 504;

    private FragmentActivity activity;

    public RequestErrorHelper(FragmentActivity activity) {
        this.activity = activity;
    }

    public void resume() {
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }
    }

    public void pause() {
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(RequestErrorEvent event) {
        if (event != null && activity != null) {
            checkError(activity, event.exception);
        } else {

        }
    }

    private void checkError(final Activity activity, Throwable e) {
        Log.e("RequestErrorHelper", exception(e));

        //   * 1.网络错误
        if (e instanceof SocketTimeoutException) {
            showNetErrorDialog(activity, "请求超时(SocketTimeoutException)");
        } else if (e instanceof ConnectException) {
            showNetErrorDialog(activity, "连接异常 ConnectException （服务器关闭 或 未网络连接)");
        } else if (e instanceof UnknownHostException) {
            showNetErrorDialog(activity, "未知主机异常,服务器地址输入错误或未连接网络");
        } else if (e instanceof SocketException) {
            showNetErrorDialog(activity, "网络错误: 连接超时");
        }

        //   * 2.服务器http状态码错误
        else if (e instanceof HttpException) {
            HttpException httpException = (HttpException) e;
            switch (httpException.code()) {
                case UNAUTHORIZED:
                case FORBIDDEN:
                    showHttpCodeErrorDialog(activity, "请求权限异常");
                    break;
                case REQUEST_ERROR:
                    showHttpCodeErrorDialog(activity, "请求链接参数错误 - 400");
                    break;
                case NOT_FOUND:
                    showHttpCodeErrorDialog(activity, "未找到服务器 - 404");
                    break;
                case REQUEST_TIMEOUT:
                case GATEWAY_TIMEOUT:
                    showHttpCodeErrorDialog(activity, "客户端请求超时,请重试");
                    break;
                case INTERNAL_SERVER_ERROR:
                    showHttpCodeErrorDialog(activity, "服务器内部错误 - 500");
                    break;
                case BAD_GATEWAY:
                    showHttpCodeErrorDialog(activity, "网关异常 - 502");
                    break;
                case SERVICE_UNAVAILABLE:
                    showHttpCodeErrorDialog(activity, "服务不可用 - 503");
                    break;
                default:
                    showHttpCodeErrorDialog(activity, "Http错误:" + httpException.code());
                    break;

            }
        }
        // * 3.Gson解析错误
        else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException) {
            showJsonParseErrorDialog(activity, "Json解析错误");
        } else if (e instanceof com.google.gson.stream.MalformedJsonException) {
            showJsonParseErrorDialog(activity, "Json解析错误");
        }
        // * 5.前端代码中异常 （onNext 方法中代码）
        else if (e instanceof NullPointerException) {
            showAndroidErrorDialog(activity, exception(e));
        } else if (e instanceof EOFException) {
            showEOFException(activity, exception(e), new TipsErrorDialog.OnOkButtonClickListener() {
                @Override
                public void onOkButtonClick() {

                }
            });
        } else {
            showUnKnowErrorDialog(activity, exception(e));
        }
    }


    private void showEOFException(Activity activity, String exception, TipsErrorDialog.OnOkButtonClickListener listener) {
        TipsErrorDialog.show(activity, "EOFException", exception, listener);
    }


    public void showNetErrorDialog(final Activity activity, String mesage) {
        TipsErrorDialog.show(activity, "网络异常", mesage, new TipsErrorDialog.OnOkButtonClickListener() {
            @Override
            public void onOkButtonClick() {
            }
        });
    }

    public void showHttpCodeErrorDialog(Activity activity, String mesage) {
        TipsErrorDialog.show(activity, "http状态异常", mesage);
    }

    public void showJsonParseErrorDialog(Activity activity, String mesage) {
        TipsErrorDialog.show(activity, "Json解析错误", mesage);
    }

    public void showAndroidErrorDialog(Activity activity, String mesage) {
        TipsErrorDialog.show(activity, "系统(前端)异常", mesage);
    }

    public void showUnKnowErrorDialog(Activity activity, String mesage) {
        TipsErrorDialog.show(activity, "未知异常", mesage);
    }

    /**
     * 将异常信息转化成字符串
     * 解决bug  在onNext方法中异常用 e.printStackTrace不能在控制台中打印错误信息
     *
     * @param t
     * @return
     */
    private static String exception(Throwable t) {
        if (t == null) {
            return "未知异常";
        } else {
            return t.getMessage();
        }
    }

    public void destroy() {
        activity = null;
    }
}
